package com.ly.nio;
import java.awt.print.Pageable;
import java.io.*;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.file.Files;
import	java.nio.file.StandardOpenOption;

import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Stack;

/**
 * @Classname NioChannel
 * @Description
 * 通道(channel):用于源节点与目标节点的连接，在java nio中负责缓冲区数据的传输
 *channel本身不储存数据，需要配合buffer
 *
 * 通道的主要实现类
 * FileChannel
 *
 * 获取通道
 * 1.txt. getChannel（）
 *    本地IO
 *    FileInputStream/FileOutputStream/RandomAccessFile
 *
 *    网络IO
 *    NioBlock
 *    ServerSocket
 *    DatagramSocket
 * 2. 各个通道提供了静态方法 open
 * 3. Files工具类的newByteChannel
 *
 * 通道之间的数据传输
 * transferFrom
 * transferTo
 *
 * 分散读取 与 聚集写入
 * 分散读取：将通道中的数据分散到多个缓冲区
 * 聚集写入：将多个缓冲区的数据聚集到通道中
 *
 *
 * 字符集
 * 编码: 字符串 -> 字符数组
 * 解码: 字节数组 -> 字符串
 *
 * @Date 2020/9/30 15:19
 * @Author 冷心影翼
 */
public class NioChannel {

	public static void main(String[] args) throws IOException {
//		way1();
//		way2();
//		way3();
//		transfer();
//		randomAccessFile();
//		charBuffer();


	}

	public static void charBuffer() throws CharacterCodingException {
		Charset cs = Charset.forName("utf-8");

		CharsetEncoder ce = cs.newEncoder();

		CharsetDecoder cd = cs.newDecoder();

		CharBuffer cb = CharBuffer.allocate(1024);
		cb.put("12345");
		cb.flip();

		//编码
		ByteBuffer bb = ce.encode(cb);

//		byte[] bytes = new byte[bb.limit()];
//		bb.get(bytes);
//		System.out.println(new String(bytes));
//
//		bb.flip();

		//解码
		CharBuffer decode = cd.decode(bb);
		System.out.println(decode.get());
		System.out.println(decode.get());
		System.out.println(decode.get());
	}

	public static void randomAccessFile() throws IOException {
		RandomAccessFile raf = new RandomAccessFile("src/nio/test.txt","r");
		FileChannel channel = raf.getChannel();

		//分散读取
		ByteBuffer b1 = ByteBuffer.allocate(6);
		ByteBuffer b2 = ByteBuffer.allocate(1024);
		ByteBuffer[] buffers = {b1,b2};

		channel.read(buffers);

		for (ByteBuffer buffer : buffers) {
			buffer.flip();
		}


		//聚集写入
		RandomAccessFile rafw = new RandomAccessFile("src/nio/wwwww.txt", "rw");
		FileChannel channel2 = rafw.getChannel();
		channel2.write(buffers);
	}

	public static void transfer() throws IOException {
		FileChannel inChnnel = FileChannel.open(Paths.get("src/nio/test.txt"), StandardOpenOption.READ);
		FileChannel outChnnel = FileChannel.open(Paths.get("src/nio/wwww.txt"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);

//		inChnnel.transferTo(0,inChnnel.size(),outChnnel);
		outChnnel.transferFrom(inChnnel,0,inChnnel.size());

		inChnnel.close();
		outChnnel.close();


	}

	public static void way3() throws IOException {
		SeekableByteChannel inChnnel = Files.newByteChannel(Paths.get("src/main/java/com/ly/nio/test.txt"), StandardOpenOption.READ);
		SeekableByteChannel outChnnel = Files.newByteChannel(Paths.get("src/main/java/com/ly/nio/www.txt"), StandardOpenOption.WRITE,StandardOpenOption.APPEND);
		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

		while (inChnnel.read(byteBuffer) != -1) {
			byteBuffer.flip();
			outChnnel.write(byteBuffer);
			byteBuffer.clear();
		}

		inChnnel.close();
		outChnnel.close();
	}

	public static void way2() throws IOException {
		FileChannel inChnnel = FileChannel.open(Paths.get("src/nio/test.txt"), StandardOpenOption.READ);
		//create_new 有相同文件保存 ，create 覆盖
		FileChannel outChnnel = FileChannel.open(Paths.get("src/nio/www.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);

		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

		//非直接内存读取
//		while (inChnnel.read(byteBuffer) != -1.txt) {
//			byteBuffer.flip();
//			outChnnel.write(byteBuffer);
//			byteBuffer.clear();
//		}

		//直接内存读取
		//READ_WRITE 需要在通道声明的时候，加入读和写
		MappedByteBuffer outMap = outChnnel.map(FileChannel.MapMode.READ_WRITE, 0, inChnnel.size());
		MappedByteBuffer inMap = inChnnel.map(FileChannel.MapMode.READ_ONLY, 0, inChnnel.size());

		byte[] bytes = new byte[inMap.limit()];
		inMap.get(bytes);
		outMap.put(bytes);

		inChnnel.close();
		outChnnel.close();

	}


	public static void way1() throws IOException {
		FileInputStream	fis = new FileInputStream("src/nio/test.txt");
		FileOutputStream	fos = new FileOutputStream("src/nio/w.txt");

		FileChannel	inChnnel = fis.getChannel();
		FileChannel	outChnnel = fos.getChannel();
		ByteBuffer buf  = ByteBuffer.allocateDirect(1024);
		while (inChnnel.read(buf) != -1) {
			buf.flip();
			outChnnel.write(buf);
			buf.clear();
		}

		fis.close();
		fos.close();
		inChnnel.close();
		outChnnel.close();
	}
}
